package com.study.springsecurity.controller;

import com.study.springsecurity.constant.CommonConstant.Role;
import com.study.springsecurity.pojo.Result;
import com.study.springsecurity.pojo.dto.UserInfoDto;
import com.study.springsecurity.utils.SecurityContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;

/**
 * 业务接口
 */
@Slf4j
@RestController
@RequestMapping("/business")
public class BusinessController {
    /**
     * 获取当前登录用户名称
     *
     * @return
     */
    @GetMapping("/getCurrentLoginUserName")
    public Result<String> getCurrentLoginUserName() {
        String userName = SecurityContextUtil.getUserName();
        return new Result<>(userName);
    }

    /**
     * 指定角色可访问
     *
     * @return
     */
    @RolesAllowed({Role.PLAT_USER_ROLE})
    @GetMapping("/test_RolesAllowed")
    public String test_RolesAllowed() {
        return "@RolesAllowed\n"
                + "表示访问对应方法时应该具备所指定的角色。 示例:@RolesAllowed({\"user\", \"admin\"})，表示该方法只要具有\"user\", \"admin\"任意一种权限就可以访问。可以省略前缀ROLE_不写。该注解可以标注在类上，也可以标注在方法上\n";
    }

    /**
     * 所有人都可以访问
     *
     * @return
     */
    @PermitAll
    @GetMapping("/test_PermitAll")
    public String test_PermitAll() {
        return "@PermitAll \n" +
                "表示允许所有的角色进行访问。@PermitAll可以标注在方法上也可以标注在类上，当标注在方法上时则只对对应方法不进行权限控制，而标注在类上时表示对类里面所有的方法都不进行权限控制 \n";
    }

    /**
     * 所有角色都不能访问
     *
     * @return
     */
    @DenyAll
    @GetMapping("/test_DenyAll")
    public String test_DenyAll() {
        return "@DenyAll \n" +
                "表示什么角色都不能访问。@DenyAll可以标注在方法上也可以标注在类上，当标注在方法上时则只对对应方法进行权限控制，而标注在类上时表示对类里面所有的方法都进行权限控制。\n";
    }

    /**
     * 判断是否具有指定的角色权限，需要加"ROLE_"前缀
     *
     * @return
     */
    @Secured({Role.ROLE_PREFIX + Role.PLAT_USER_ROLE})
    @GetMapping("/test_Secured")
    public String test_Secured() {
        return "@Secured \n" +
                "由 Spring Security 定义的，用来支持方法权限控制的注解。@Secured 专门用于判断是否具有指定角色的，可以写在方法或类上。参数需要手动指定 \"ROLE_\" 前缀。\n";
    }

    /**
     * 在方法调用前进行权限检查
     *
     * @return
     */
    @PreAuthorize("hasRole(T(com.study.springsecurity.constant.CommonConstant.Role).PLAT_MANAGE_ROLE) or hasAuthority('test_Secured')")
    //@PreAuthorize("hasRole('PLAT_MANAGE') or hasAuthority('test_Secured')")
    @GetMapping("/test_1_PreAuthorize")
    public String test_1_PreAuthorize() {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

    @PreAuthorize("@adminRoleCheck.check(authentication)")
    @GetMapping("/test_2_PreAuthorize")
    public String test_2_PreAuthorize() {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

    @PreAuthorize("@adminRoleCheck.check(authentication,#name)")
    @GetMapping("/test_2_1_PreAuthorize")
    public String test_2_1_PreAuthorize(String name) {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

    @PreAuthorize("hasPermission(#id, 'QUERY')")
    @GetMapping("test_3_PreAuthorize")
    public String test_3_PreAuthorize(String id) {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

    @PreAuthorize("hasPermission(#id, 'TABLE', 'QUERY')")
    @GetMapping("test_4_PreAuthorize")
    public String test_4_PreAuthorize(String id,String name) {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

    @PreAuthorize("hasPermission(#userInfoDto, 'QUERY')")
    @PostMapping("test_5_PreAuthorize")
    public String test_5_PreAuthorize(@RequestBody UserInfoDto userInfoDto) {
        return "@PreAuthorize \n" +
                "最被常用的注解为@PreAuthorize。在方法调用前进行权限检查，结果为 true 则可以执行！可以在类或者方法上进行标注。注解参数与access方法参数一致，也就是说可以使用内置方法和Spring-EL表达式 \n" +
                "例如：@PreAuthorize(\"hasRole('admin') or hasRole('user')\")\n";
    }

}
